//
//  CXSelectAssetManager.swift
//  selectPhoto
//
//  Created by 孟祥群 on 2018/4/24.
//  Copyright © 2018年 孟祥群. All rights reserved.
//

import UIKit
import Photos
import MobileCoreServices
import FCUUID

typealias selectAssetsBlock = (_ imageArr:Array<UIImage>)->()
typealias selectAssetsPathBlock = (_ imageArr:Array<String>)->()
typealias SelectAssetsBlock = (_ asset:Array<PHAsset>) -> ()

class CXSelectAssetManager: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    /// 选择图片回调
    var selectBlock:selectBlock?
    /// 选择图片路径回调
    var selectPathBlock:selectAssetPathBlock?
    /// 选择相册资源回调
    var selectAssetsBlock:SelectAssetsBlock?
  
    var controller:UIViewController?
    /// 最大图片数量
    var largestNum:Int = 0
    /// 选择类型：1 - 图片   2 - 视频 3 - 图片+视频
    var selectType:Int = 1
    /// 已选择数量
    var haveNum:Int = 0
    let imageSize: CGFloat = 300
    var localId:String?
    static let manager = CXSelectAssetManager()
    
    @objc func selectPhoto(dataSource:UIViewController, maximum:Int, haveNb:Int, selectBlock:@escaping selectBlock) -> Void {
        controller = dataSource
        largestNum = maximum
        haveNum = haveNb
        self.selectBlock = selectBlock
        self.eventAddImage()
    }
    @objc func selectPhotoPaths(dataSource:UIViewController, maximum:Int, haveNb:Int, selectPathBlock:@escaping selectAssetPathBlock) -> Void {
      controller = dataSource
      largestNum = maximum
      haveNum = haveNb
      self.selectPathBlock = selectPathBlock
      self.eventAddImage()
    }
    @objc func selectAssets(dataSource:UIViewController, maximum:Int, haveNb:Int, selectAssetsBlock:@escaping SelectAssetsBlock) -> Void {
      controller = dataSource
      largestNum = maximum
      haveNum = haveNb
      self.selectAssetsBlock = selectAssetsBlock
      self.eventAddImage()
    }
  
  /// 选择视频或图片
  /// - Parameter dataSource: 原视图控制器
  /// - Parameter maximum: 最大选择数
  /// - Parameter type：1 - 图片   2 - 视频 3 - 图片+视频
  /// - Parameter haveNb: 已选择数
  /// - Parameter selectPathBlock: 回调
  @objc func selectPhotoPaths(dataSource:UIViewController, maximum:Int, selectType:Int, haveNb:Int, selectPathBlock:@escaping selectAssetPathBlock) -> Void {
      controller = dataSource
      largestNum = maximum
      self.selectType = selectType
      haveNum = haveNb
      self.selectPathBlock = selectPathBlock
      self.eventAddImage()
    }
  
    /// 选择视频或图片
    /// - Parameter dataSource: 原视图控制器
    /// - Parameter maximum: 最大选择数
    /// - Parameter type：1 - 图片   2 - 视频 3 - 图片+视频
    /// - Parameter haveNb: 已选择数
    /// - Parameter selectPathBlock: 回调
    @objc func selectAssets(dataSource:UIViewController, maximum:Int, selectType:Int, haveNb:Int, selectAssetsBlock:@escaping SelectAssetsBlock) -> Void {
        self.controller = dataSource
        self.largestNum = maximum
        self.haveNum = haveNb
        self.selectType = selectType
        self.selectAssetsBlock = selectAssetsBlock
        self.eventAddImage()
    }
    
    func eventAddImage() {
        let alert = UIAlertController.init(title: nil, message: nil, preferredStyle: .actionSheet)
        
        // change the style sheet text color
        alert.view.tintColor = UIColor(red: 0.0, green: 0.65, blue: 0.95, alpha: 1.0)
        
        let actionCancel = UIAlertAction.init(title: "取消", style: .cancel, handler: nil)
        alert.addAction(actionCancel)
        
        if self.selectType == 1 || self.selectType == 3 {
            let actionCamera = UIAlertAction.init(title: "拍照", style: .default) { (UIAlertAction) -> Void in
                self.selectByCamera()
            }
            alert.addAction(actionCamera)
        }
        if self.selectType == 2 || self.selectType == 3 {
          let actionVideo = UIAlertAction.init(title: "拍视频", style: .default) { (UIAlertAction) -> Void in
              self.selectVideoByCamera()
          }
          alert.addAction(actionVideo)
        }
        
        let actionPhoto = UIAlertAction.init(title: "从相册选择上传", style: .default) { (UIAlertAction) -> Void in
            self.selectFromPhoto()
        }
        alert.addAction(actionPhoto)
        
        controller?.present(alert, animated: true, completion: nil)
    }
    // 拍照获取
    private func selectByCamera(){
        if UIImagePickerController.isSourceTypeAvailable(.camera) {
            
            let imagePicker = UIImagePickerController()
            imagePicker.sourceType = .camera // 调用摄像头
            imagePicker.cameraCaptureMode = .photo // 拍照
            if UIImagePickerController.isCameraDeviceAvailable(.rear) {
                
                imagePicker.cameraDevice = .rear // 后置摄像头拍照
            }
            imagePicker.allowsEditing = false
            imagePicker.delegate = self
            imagePicker.mediaTypes = [kUTTypeImage as String]
            
            imagePicker.modalPresentationStyle = .overFullScreen
            controller?.show(imagePicker, sender: nil)
        }
    }
    func selectVideoByCamera(){
//      let vc = IWVideoRecordingController
      let recordVC = IWVideoRecordingController()
      recordVC.modalPresentationStyle = .overFullScreen
      recordVC.delegate = self
      self.controller?.present(recordVC, animated: true, completion: nil)
    }
    // MARK: -  拍照 delegate相关方法
    // 退出拍照
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
    }
    
    
    // 完成拍照
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true, completion: nil)
        let mediaType = info[UIImagePickerController.InfoKey.mediaType] as! String;
        var image: UIImage? = nil
        if picker.isEditing { // 拍照图片运行编辑，则优先尝试从编辑后的类型中获取图片
            image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage
        }else{
            image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
        }
        guard let photoImage = image else { return }

        if let tempSelectBlock = selectBlock {
            if mediaType == kUTTypeImage as String { // 图片类型
                tempSelectBlock([photoImage])
            }
        }
        if let tempSelectPathBlock = selectPathBlock {
            selectPathBlock = nil
            PHPhotoLibrary.shared().performChanges({
                let result = PHAssetChangeRequest.creationRequestForAsset(from: photoImage)
                let assetPlaceholder = result.placeholderForCreatedAsset
                self.localId = assetPlaceholder?.localIdentifier
            }) {[weak self] (isSuccess, error) in
                guard let `self` = self else {
                    tempSelectPathBlock([])
                    return
                }
                if isSuccess {
                    //通过标志符获取对应的资源
                    let assetResult = PHAsset.fetchAssets(withLocalIdentifiers: [self.localId ?? ""], options: nil)
                    if assetResult.count <= 0 {
                        tempSelectPathBlock([])
                        return
                    }
                    let phAsset = assetResult[0]
                    // 获取到 asset
                    if phAsset.mediaType == .video {
                        let options = PHVideoRequestOptions()
                        options.version = .original
                        options.isNetworkAccessAllowed = true
                        options.deliveryMode = .highQualityFormat
                        PHCachingImageManager.default().requestAVAsset(forVideo: phAsset, options: options, resultHandler: { (avAsset, audioMix, info) in
                            guard let tempAVAsset = avAsset else {
                                tempSelectPathBlock([])
                                return
                            }
//                            if let tempInfo = info as? [String:Any],let strPHImageFileSandboxExtensionToken = tempInfo["PHImageFileSandboxExtensionTokenKey"] as? String {
//                                let arr = strPHImageFileSandboxExtensionToken.components(separatedBy: ";")
//                                if let path = arr.last {
//                                    tempSelectPathBlock([path])
//                                } else {
//                                    tempSelectPathBlock([])
//                                }
//                                return
//                            }
                            let tempName = FCUUID.uuid()!
                            CFAsmanFileManager.startExportVideoWithVideoAsset(asset: tempAVAsset, fileName: tempName) { (fileName, path) in
                                guard let outputPath = path else {
                                    tempSelectPathBlock([])
                                    return
                                }
                                tempSelectPathBlock([outputPath])
                            }
                        })
                    } else if phAsset.mediaType == .image {
                        phAsset.getImageAsync { (image) in
                            guard let tempImage = image else {
                                tempSelectPathBlock([])
                                return
                            }
                            tempImage.saveImage(didCompleted: { (imagePath, error) in
                                if let tempImagePath = imagePath {
                                    tempSelectPathBlock([tempImagePath])
                                } else {
                                    tempSelectPathBlock([])
                                }
                            })
                        }
                    }else{
                        tempSelectPathBlock([])
                    }
                } else {
                    tempSelectPathBlock([])
                }
            }
        }
        
        if let tempSelectAssetsBlock = self.selectAssetsBlock {
            PHPhotoLibrary.shared().performChanges({
                let result = PHAssetChangeRequest.creationRequestForAsset(from: photoImage)
                let assetPlaceholder = result.placeholderForCreatedAsset
                self.localId = assetPlaceholder?.localIdentifier
            }) { (isSuccess, error) in
                if isSuccess {
                    //通过标志符获取对应的资源
                    let assetResult = PHAsset.fetchAssets(
                    withLocalIdentifiers: [self.localId ?? ""], options: nil)
                    let asset = assetResult[0]
                    tempSelectAssetsBlock([asset])
                }else{
                    tempSelectAssetsBlock([])
                }
            }
        }
    }
    
    /**
     * 从相册中选择图片
     */
    private func selectFromPhoto(){
        PHPhotoLibrary.requestAuthorization {[unowned self] (status) -> Void in
            DispatchQueue.main.async {
                switch status {
                case .authorized:
                    self.showLocalPhotoGallery()
                    break
                default:
                    self.showNoPermissionDailog()
                    break
                }
            }
        }
    }
    /**
     * 用户相册未授权，Dialog提示
     */
    private func showNoPermissionDailog(){
        let alert = UIAlertController.init(title: nil, message: "没有打开相册的权限", preferredStyle: .alert)
        alert.addAction(UIAlertAction.init(title: "确定", style: .default, handler: nil))
        controller?.present(alert, animated: true, completion: nil)
    }
    
    /**
     * 打开本地相册列表
     */
    private func showLocalPhotoGallery(){
        // TODO： 。。。。
        var mediaTypes = [MTImagePickerMediaType]()
        if self.selectType == 1 || self.selectType == 3 {
            mediaTypes.append(MTImagePickerMediaType.Photo)
        }
        if self.selectType == 2 || self.selectType == 3 {
            mediaTypes.append(MTImagePickerMediaType.Video)
        }
//        switch self.selectType {
//        case 1:
//            mediaTypes.append(MTImagePickerMediaType.Photo)
//        default:
//            mediaTypes.append(MTImagePickerMediaType.Photo)
//            mediaTypes.append(MTImagePickerMediaType.Video)
//        }
        let source = MTImagePickerSource.Photos
        var defaultShowCameraRoll = false
        defaultShowCameraRoll = true
        let vc = MTImagePickerController.instance
        vc.mediaTypes = mediaTypes
        vc.source = source
        vc.imagePickerDelegate = self
        vc.maxCount = self.largestNum
        vc.defaultShowCameraRoll = defaultShowCameraRoll
        vc.modalPresentationStyle = .overFullScreen
        self.controller?.present(vc, animated: true, completion: nil)
    }
    
    func onImageSelectFinished(images: [PHAsset]) {
        
    }
    
}

extension CXSelectAssetManager {
    @objc public static func sharedInstance() -> CXSelectAssetManager{
      return manager;
    }
}
    extension CXSelectAssetManager : IWVideoRecordingDelegate {
        func recordCancel(_ viewController: IWVideoRecordingController) {
            viewController.dismiss(animated: true, completion: nil)
        }

        func recordCompleted(_ viewController:IWVideoRecordingController,videoPath:String){
            viewController.dismiss(animated: true, completion: nil)
            if let tempSelectPathBlock = self.selectPathBlock {
                selectPathBlock = nil
                PHPhotoLibrary.shared().performChanges({
                    let result = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: URL(string: videoPath)!)!
                    let assetPlaceholder = result.placeholderForCreatedAsset
                    self.localId = assetPlaceholder?.localIdentifier
                }) { (isSuccess, error) in
                    if isSuccess {
                        //通过标志符获取对应的资源
                        let assetResult = PHAsset.fetchAssets(withLocalIdentifiers: [self.localId ?? ""], options: nil)
                        if assetResult.count <= 0 {
                            tempSelectPathBlock([])
                            return
                        }
                        let phAsset = assetResult[0]
                        // 获取到 asset
                        if phAsset.mediaType == .video {
                            let options = PHVideoRequestOptions()
                            options.version = .original
                            options.isNetworkAccessAllowed = true
                            options.deliveryMode = .highQualityFormat
                            PHCachingImageManager.default().requestAVAsset(forVideo: phAsset, options: options, resultHandler: { (avAsset, audioMix, info) in
                                guard let tempAVAsset = avAsset else {
                                    tempSelectPathBlock([])
                                    return
                                }
                                let tempName = FCUUID.uuid()!
                                CFAsmanFileManager.startExportVideoWithVideoAsset(asset: tempAVAsset, fileName: tempName) { (fileName, path) in
                                    guard let outputPath = path else {
                                        tempSelectPathBlock([])
                                        return
                                    }
                                    tempSelectPathBlock([outputPath])
                                }
                            })
                        } else if phAsset.mediaType == .image {
                            phAsset.getImageAsync { (image) in
                                guard let tempImage = image else {
                                    tempSelectPathBlock([])
                                    return
                                }
                                tempImage.saveImage(didCompleted: { (imagePath, error) in
                                    if let tempImagePath = imagePath {
                                        tempSelectPathBlock([tempImagePath])
                                    } else {
                                        tempSelectPathBlock([])
                                    }
                                })
                            }
                        }else{
                            tempSelectPathBlock([])
                        }
                    }else{
                        tempSelectPathBlock([])
                    }
                }
            }
            if let tempSelectAssetsBlock = self.selectAssetsBlock {
                selectAssetsBlock = nil
                PHPhotoLibrary.shared().performChanges({
                    let result = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: URL(string: videoPath)!)!
                    let assetPlaceholder = result.placeholderForCreatedAsset
                    self.localId = assetPlaceholder?.localIdentifier
                }) { (isSuccess, error) in
                    if isSuccess {
                        //通过标志符获取对应的资源
                        let assetResult = PHAsset.fetchAssets(withLocalIdentifiers: [self.localId ?? ""], options: nil)
                        let asset = assetResult[0]
                        if assetResult.count <= 0 {
                            tempSelectAssetsBlock([])
                            return
                        }
                        tempSelectAssetsBlock([asset])
                    }else{
                        tempSelectAssetsBlock([])
                    }
                }
            }
        }
    }
extension CXSelectAssetManager: MTImagePickerControllerDelegate {
    
    @available(iOS 8.0, *)
    func imagePickerController(picker: MTImagePickerController, didFinishPickingWithPhotosModels models: [MTImagePickerPhotosModel]) {
        if let tempSelectAssetsBlock = self.selectAssetsBlock {
            let assets = models.map{ $0.phasset }
            tempSelectAssetsBlock(assets as! Array<PHAsset>)
        }
        if let tempSelectPathsBlock = self.selectPathBlock {
          var imagePaths:[String] = []
          var remainCount = models.count
          DispatchQueue.main.async {
  //            UIApplication.shared.keyWindow?.cx_showLoading(with: "正在准备上传图片和视频，请稍后...")
              UIApplication.shared.keyWindow?.cx_showLoading(with: "正在准备上传的图片和视频，请稍后...", cancelAction: {
                  self.selectPathBlock?([])
                  self.selectPathBlock = nil
                  DispatchQueue.main.async {
                      UIApplication.shared.keyWindow?.cx_removeLoading()
                  }
              })
              DispatchQueue.global().async {
                  models.forEach { (model) in
                    if model.phasset.mediaType == .video {
                      let options = PHVideoRequestOptions()
                      options.version = .original
                      options.isNetworkAccessAllowed = true
                      options.deliveryMode = .highQualityFormat
                      PHCachingImageManager.default().requestAVAsset(forVideo: model.phasset, options: options, resultHandler: { (asset, audioMix, info) in
                          guard let tempAsset = asset else {
                              remainCount -= 1
                              if remainCount <= 0 {
                                  print(imagePaths.description)
                                  DispatchQueue.main.async {
                                    self.selectPathBlock?(imagePaths)
                                    self.selectPathBlock = nil
                                      UIApplication.shared.keyWindow?.cx_removeLoading()
                                  }
                              }
                              return
                          }
                          if let tempInfo = info as? [String:Any],let strPHImageFileSandboxExtensionToken = tempInfo["PHImageFileSandboxExtensionTokenKey"] as? String {
                              let arr = strPHImageFileSandboxExtensionToken.components(separatedBy: ";")
                              if let path = arr.last {
                                  imagePaths.append(path)
                              }
                              remainCount -= 1
                              if remainCount <= 0 {
                                  print(imagePaths.description)
                                  tempSelectPathsBlock(imagePaths)
                                  DispatchQueue.main.async {
                                      UIApplication.shared.keyWindow?.cx_removeLoading()
                                      UIApplication.shared.keyWindow?.isUserInteractionEnabled = true
                                      self.selectPathBlock = nil
                                      UIApplication.shared.keyWindow?.cx_removeLoading()
                                  }
                              }
                              return
                          }
                          let tempName = FCUUID.uuid()!
                          CFAsmanFileManager.startExportVideoWithVideoAsset(asset: tempAsset, fileName: tempName) {[weak self] (fileName, path) in
                              guard let `self` = self else { return }
                              guard let outputPath = path else {
                                  print("export fail")
                                  remainCount -= 1
                                  if remainCount <= 0 {
                                      print(imagePaths.description)
                                      DispatchQueue.main.async {
                                          self.selectPathBlock?(imagePaths)
                                          self.selectPathBlock = nil
                                          UIApplication.shared.keyWindow?.cx_removeLoading()
                                      }
                                  }
                                  return
                              }
                              imagePaths.append(outputPath)
                              remainCount -= 1
                              if remainCount <= 0 {
                                  print(imagePaths.description)
                                  tempSelectPathsBlock(imagePaths)
                                  DispatchQueue.main.async {
                                      self.selectPathBlock?(imagePaths)
                                      self.selectPathBlock = nil
                                      UIApplication.shared.keyWindow?.cx_removeLoading()
                                  }
                              }
                          }
                      })
                  }
                  else if model.phasset.mediaType == .image {
                      model.getImageAsync(complete: { (image) in
                        assert(image != nil, "图片不存在")
                        image!.saveImage(didCompleted: {[weak self] (imagePath, error) in
                          guard let `self` = self else { return }
                          imagePaths.append(imagePath!)
                          remainCount -= 1
                          if remainCount <= 0 {
                            print(imagePaths.description)
                            tempSelectPathsBlock(imagePaths)
                            DispatchQueue.main.async {
                                UIApplication.shared.keyWindow?.cx_removeLoading()
                                UIApplication.shared.keyWindow?.isUserInteractionEnabled = true
                            }
                          }
                        })
                      })
                    }else{
                        remainCount -= 1
                        if remainCount <= 0 {
                            print(imagePaths.description)
                            tempSelectPathsBlock(imagePaths)
                            DispatchQueue.main.async {
                                UIApplication.shared.keyWindow?.cx_removeLoading()
                                UIApplication.shared.keyWindow?.isUserInteractionEnabled = true
                            }
                        }
                    }
              }
              }
          }
        }
    }
    
    func imagePickerController(picker: MTImagePickerController, didFinishPickingWithAssetsModels models: [MTImagePickerAssetsModel]) {
        let imagePaths = models.map{ $0.getIdentity() }
        print(imagePaths.description)
    }
    
    func imagePickerControllerDidCancel(picker: MTImagePickerController) {
        print("cancel")
    }
}
class CXShowAssetsManager: NSObject {
  var controller:UIViewController?
  
  static let manager = CXShowAssetsManager()
  @objc static func sharedInstance() -> CXShowAssetsManager {
    return manager;
  }
  @objc func show(controller:UIViewController,assetPaths:[[String:Any]],currentIndex:Int = 0){
      let photoAssets = assetPaths.map { (pathMap) -> CXPhotoAsset in
          let type = pathMap["type"] as! String
          let path = pathMap["path"] as! String
          let title = pathMap["title"] as? String ?? ""
          var asset:CXPhotoAsset? = nil
          if type == "video" {
            asset = CXPhotoAsset(type: .video, path: path, title:title)
          }else{
            asset = CXPhotoAsset(type: .image, path: path, title:title)
          }
          return asset!
        }
        let browser = CXPhotoBrowser()
        browser.picAssets = photoAssets
        browser.currentIndex = currentIndex
        browser.show()
    }
}
